////////////////////////////////////////////////////////////////
// 3DObject_GL.h
// OpenGL Screen implmentation
//
////////////////////////////////////////////////////////////////

#ifndef _OBJECT3D_GL
#define _OBJECT3D_GL

#define DEBUG

#include "..\framework\Frm_Mesh.h" //based on the correct Mesh element
#include "Screen_GL.h"

class ObjectBone{
	public:
	ObjectBone(void): _Bone(0), _Animation(0){_TransformMatrix.Identity(); _CombinedMatrix.Identity(); _FinalMatrix.Identity();};
	~ObjectBone(void);

   inline void CalcAttitude(ObjectBone* &pParentBone); //compute the Final Matrix
   void CalcAnimation(uint16 &pKey); //retrieves a transformation matrice from an animation
   void CalcBindSpace(void){_TransformMatrix = _Bone->_MatrixPos;}; //Sets up the original Matrix position as transformation matrix

   Frm::Bone* _Bone;
   Frm::Animation* _Animation;
   uint16 _AnimationIndexMat, _AnimationIndexS, _AnimationIndexR, _AnimationIndexT;
   Frm::Matrix _TransformMatrix, _CombinedMatrix, _FinalMatrix;
   std::string _BoneName;
   std::list<ObjectBone*> _Bones;
};/**/

class Object3D
{
   public:
		Object3D(void):_Skeletton(0), _SkinnedVertices(0), _Model(0), _AnimationStep(1){};
      ~Object3D(void){if (_SkinnedVertices!=0) delete[] _SkinnedVertices; /*if (_Skeletton!=0) delete _Skeletton;/**/}
      void SetupModel(Frm::Model3D* &pModel){
      	_Model = pModel;
         _Mesh = _Model->_Meshes.front();
         _SkinnedVertices = new Frm::Vertex[_Mesh->_nVertices];
         _Skeletton = ReplicateSkeletton(_Model->_Skeletton);
         };

      //Vertices to render
      void ClearSkinnedVertices(void){memset(_SkinnedVertices, 0, _Mesh->_nVertices * sizeof(Frm::Vertex));};

      //Animation Based
      void SetAnimationStep(uint16 pStep){_AnimationStep = pStep;};
		void MapAnimationSet(std::string pText="None");
      void MapAnimationSet(uint16 &index);
      void UpdateAnimation(void){_cKey += _AnimationStep; if (_cKey > _cAnimationSet->_MaxKey) _cKey = 0; CalcAnimation(_Skeletton); ComputeBoundingBoxSphere(); CalcAttitude(_Skeletton,0); SkinMesh(_Skeletton);};
      void UpdateBindSpace(void){CalcBindSpace(_Skeletton);CalcAttitude(_Skeletton,0);SkinMesh(_Skeletton);};
      inline void CalcAnimation(void){	_cKey += _AnimationStep; if (_cKey > _cAnimationSet->_MaxKey)	_cKey = 0; CalcAnimation(_Skeletton); ComputeBoundingBoxSphere();};
      inline void CalcBindSpace(void){CalcBindSpace(_Skeletton);};
      inline void Update(void){CalcAttitude(_Skeletton,0);SkinMesh(_Skeletton);};
      void Draw(Screen_GL* pScreen);

      void ComputeBoundingBoxSphere(void);
      //Elements for the AABB (_Low & _High)
      //and bounding sphere (_Center & _Radius)
      Frm::Vertex _Low, _High, _Center;
      float _Radius;

   private:
      ObjectBone* _Skeletton;
      Frm::Mesh* _Mesh; //pointer to Model Mesh
      Frm::Vertex* _SkinnedVertices;
		Frm::Model3D* _Model;
      Frm::AnimationSet* _cAnimationSet;

      uint16 _cKey; //current animation Key
      uint16 _AnimationStep; //Animation Increment

      ObjectBone* ReplicateSkeletton(Frm::Bone* &pBone);
      void GetBoneAnimation(ObjectBone* &pBone);
      void CalcAttitude(ObjectBone* pBone, ObjectBone* pParentBone);
      void CalcAnimation(ObjectBone* &pBone);
      void CalcBindSpace(ObjectBone* &pBone);
      void SkinMesh(ObjectBone* &pParentBone);/**/
};

#endif
